#include "Reactor/TcpConnection.h"
#include "Reactor/EventLoop.h"

#include <iostream>
#include <sstream>
#include <strings.h>
#include <string.h>
#include <curl/curl.h>
#include "Log/Log.hh"
using std::cout;
using std::endl;
using std::ostringstream;

TcpConnection::TcpConnection(int fd, EventLoop *loop)
: _loop(loop)
, _sockIO(fd)
, _sock(fd)
, _localAddr(getLocalAddr())
, _peerAddr(getPeerAddr())
{

}

TcpConnection::~TcpConnection()
{

}

void TcpConnection::send(const string &msg)
{
    _sockIO.writen(msg.c_str(), msg.size());
}

void TcpConnection::sendInLoop(const string &msg)
{
    if(_loop)
    {
        _loop->runInLoop(bind(&TcpConnection::send, this, msg));
    }
}



std::string urlDecode(const std::string& encodedString) {
    CURL* curl = curl_easy_init();
    char* decodedString = curl_easy_unescape(curl, encodedString.c_str(), 0, NULL);
    std::string result(decodedString);
    curl_free(decodedString);
    curl_easy_cleanup(curl);
    return result;
}

string TcpConnection::receive()
{
    char buff[65535] = {0};
    // 读一行
    string method;
    string arg;
    string msg;
    while(1){
        ::bzero(buff, sizeof(buff));
        _sockIO.readLine(buff, sizeof(buff));
        if(strcmp(buff, "\r\n") == 0){break;}

        if(memcmp(buff, "GET /", 5) == 0){
            if(memcmp(buff, "GET /suggest/", 13) == 0){
                arg = urlDecode(string(buff).substr(13, strlen(buff) - 24)); // Remove "/search/" prefix
                msg = "100" + arg;
                // 100 是推荐
            }
            else if(memcmp(buff, "GET /search/", 12) == 0){
                arg = urlDecode(string(buff).substr(12, strlen(buff) - 23));
                msg = "200" + arg;
                // 200 是搜索
            }
        }
    }
    Log::info("recv msg: %s %s", method.c_str(), arg.c_str());
    if(msg.size() == 0){}
    return string(msg);
}

bool TcpConnection::isClosed() const
{
    char buff[10] = {0};
    int ret = recv(_sock.fd(), buff, sizeof(buff), MSG_PEEK);
    return (0 == ret);
}

string TcpConnection::toString()
{
    ostringstream oss;
    oss << _localAddr.ip() << ":"
        << _localAddr.port() << "---->"
        << _peerAddr.ip() << ":"
        << _peerAddr.port();

    return oss.str();
}

//获取本端的网络地址信息
InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr );
    //获取本端地址的函数getsockname
    int ret = getsockname(_sock.fd(), (struct sockaddr *)&addr, &len);
    if(-1 == ret)
    {
        perror("getsockname");
    }

    return InetAddress(addr);
}

//获取对端的网络地址信息
InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr );
    //获取对端地址的函数getpeername
    int ret = getpeername(_sock.fd(), (struct sockaddr *)&addr, &len);
    if(-1 == ret)
    {
        perror("getpeername");
    }

    return InetAddress(addr);
}

//三个回调的注册
void TcpConnection::setNewConnectionCallback(const TcpConnectionCallback &cb)
{
    _onNewConnection = cb;
}

void TcpConnection::setMessageCallback(const TcpConnectionCallback &cb)
{
    _onMessage = cb;
}

void TcpConnection::setCloseCallback(const TcpConnectionCallback &cb)
{
    _onClose = cb;
}

//三个回调的执行
void TcpConnection::handleNewConnectionCallback()
{
    if(_onNewConnection)
    {
        //using TcpConnectionPtr = shared_ptr<TcpConnection>;
        //using TcpConnectionCallback = function<void(const TcpConnectionPtr &)>
        /* _onNewConnection(shared_ptr<TcpConnection>(this)); */
        _onNewConnection(shared_from_this());//为了防止智能指针的误用
    }
    else
    {
        cout << "nullptr == _onNewConnection" << endl;
    }
}

void TcpConnection::handleMessageCallback()
{
    if(_onMessage)
    {
        _onMessage(shared_from_this());
    }
    else
    {
        cout << "nullptr == _onMessage" << endl;
    }
}

void TcpConnection::handleCloseCallback()
{
    if(_onClose)
    {
        _onClose(shared_from_this());
    }
    else
    {
        cout << "nullptr == _onClose" << endl;
    }
}
